package core.util
{
	import com.adobe.serialization.json.JSON;
	
	import core.command.SuperCommand;
	import core.data.DataBase;
	import core.event.SocketEventID;
	import core.event.UnoEvent;
	import core.event.ViewEventID;
	import core.listener.GlobalListener;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	
	public class SocketUtil extends EventDispatcher
	{
		///////////////////////////////////////////////////////////////////////////////////
		public function SocketUtil(lock:Lock)
		{
			if(lock == null)
			{
				throw new Error("SocketUtil can not be init");
			}
		}
		
		private static var _socketInstance:SocketUtil = null;
		public static function getInstance():SocketUtil
		{
			if(_socketInstance == null)
			{
				_socketInstance = new SocketUtil(new Lock());
			}
			return _socketInstance;
		}
		/////////////////////////////////////////////////////////////////////////////////////
		private var db:DataBase = DataBase.getInstance();
		private var _socket:Socket = null;
		private var dispatcher:GlobalListener = GlobalListener.getInstance();
		private function initSocket():void
		{
			_socket = new Socket();
			_socket.addEventListener(Event.CONNECT, socketHandle);
			_socket.addEventListener(Event.CLOSE, socketHandle);
			_socket.addEventListener(IOErrorEvent.IO_ERROR, onSocketError);
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityError);
            _socket.addEventListener(ProgressEvent.SOCKET_DATA, socketHandle);
            
            dispatcher.dispatchEvent(new UnoEvent(ViewEventID.SOCKET_CONNECT,"socket 初始化完成。尝试与服务器连接..."));
		}
		private function onSocketError(e:IOErrorEvent):void
		{
			trace(e);
		}
		private function onSocketSecurityError(e:SecurityErrorEvent):void
		{
			trace(e);
		}
		private function socketHandle(e:Event):void
		{
			switch(e.type)
			{
				case Event.CONNECT:
					dispatcher.dispatchEvent(new UnoEvent(SocketEventID.SOCKET_CONNECT,"服务器连接成功.正在登录..."));
					loginHandle();
					break;
				case Event.CLOSE:
					trace("socket closed");
					break;
				default:
					var msg:String = "";
               		while(e.target.bytesAvailable)
	                {
	                    //强制使用utf8格式，避免中文乱码  
	                    msg += _socket.readMultiByte(_socket.bytesAvailable, "utf-8");
	                }
					
					//使用\n换行符号把信息切开
					var msgs:Array = msg.split("\n");
					
					for each(var m:String in msgs)
					{
						if(m == "")
						{
							continue;
						}
						
						try{
	                		var response:Object = JSON.decode(m);
	                		dispatcher.dispatchEvent(new UnoEvent(response.event,response.body,response.status));
						}catch(err:Error)
						{
							trace(err);
						}
					}
					break;
			}
		}
		
		private function connect():void
        {
        	if(!_socket.connected)
        	{
            	_socket.connect("localhost", 10000);
         	}
        }
        
        private function send(msg:String):void
        {
        	if(connected)
        	{
            	_socket.writeUTFBytes(msg+"\n");
           		_socket.flush();
            }
        }
		
		public function get connected():Boolean
		{
			return _socket && _socket.connected;
		}
		
		public function injectCommand(command:Class):void
		{
			var c:SuperCommand = new command() as SuperCommand;
			dispatcher.addEventListener(c.socketEvent,c.command);
		}
		
		private function loginHandle():void
		{
			var cmd:Object = {"action":"login","para":{"userName":db.loginUser.name,"userPass":db.loginUser.password}};
			send(JSON.encode(cmd));
		}
		
		public function login():void
		{
			initSocket();
			connect();
		}
		
		public function createTable(tableName:String):void
		{
			var cmd:Object = {"action":"createTable","para":{"tableName":tableName}};
			send(JSON.encode(cmd));
		}
		
		public function joinTable(tableID:String):void
		{
			var cmd:Object = {"action":"joinTable","para":{"tableID":tableID}};
			send(JSON.encode(cmd));
		}
		
		public function ready():void
		{
			var cmd:Object = {"action":"ready","para":{}};
			send(JSON.encode(cmd));
		}
		
		public function chat(content:String,scope:String="",target:String = ""):void
		{
			trace(content);
			content = content.replace(/\\[a-fA-F0-9]?/g,"");
			trace(content);
			var cmd:Object = {"action":"chat","para":{"content":content,"scope":scope,"target":target}};
			send(JSON.encode(cmd));
		}
		
		public function standUp():void
		{
		 	var cmd:Object = {"action":"standUp","para":{}};
			send(JSON.encode(cmd));
		}
		
		public function selectRoom(roomID:String):void
		{
			var cmd:Object = {"action":"selectRoom","para":{"roomID":roomID}};
			send(JSON.encode(cmd));
		}
		
		public function playCard(cardID:String, para1:String = ""):void
		{
			var cmd:Object = {"action":"playCard","para":{"cardID":cardID, "para1":para1}};
			send(JSON.encode(cmd));
		}
		
		public function startGame():void
		{
			var cmd:Object = {"action":"start","para":{}};
			send(JSON.encode(cmd));
		}
		
		public function rollTimeout():void
		{
			var cmd:Object = {"action":"rollTimeout","para":{}};
			send(JSON.encode(cmd));
		}
		
		public function roll():void
		{
			var cmd:Object = {"action":"roll","para":{}};
			send(JSON.encode(cmd));
		}
		
		/**
		 *自已没牌出（过，超时） 
		 * 
		 */		
		public function pass():void
		{
			var cmd:Object = {"action":"pass","para":{}};
			send(JSON.encode(cmd));
		}
		
		/**
		 *其他玩家判定当前的玩家超时 
		 * 
		 */		
		public function timeout():void
		{
			
		}
		
		public function uno():void
		{
			var cmd:Object = {"action":"uno","para":{}};
			send(JSON.encode(cmd));
		}
	}
}
class Lock{}